package com.example.mianshi.mianshiv2;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.concurrent.*;

/**
 * 假设本地有一个文件夹，文件夹下面有若干文件（文件数大于50小于100），文件的存储格式是文本格式（后缀名是.txt)，文件的大小每个文件不会超过100k。
 * 文件格式如下：
 * 2000102，100，98.3
 * 2000103，101，73.3
 * 2000104，102，98.3
 * 2000105，100，101.3
 * 2000106，101，45.3
 * …
 * 文件格式说明：文件每行都由三列构成，第一列是一个id，第二列是分组groupId, 第三列是指标quota。
 * id的数据类型是String, groupId的数据类型String, quota的数据类型float。
 * 功能要求：
 * 1.把所有文件里面的内容取出来一起按照分组进行排序（注意是所有文件内容一起），输出按照分组升序排序之后，每个分组下面的最小指标值。比如上面的数据输出结果为：
 * 100，2000102，98.3
 * 101，2000106，45.3
 * 102，2000104，98.3
 * 非功能要求
 * 1.文件读取要有线程池来执行，线程池的大小固定为10，文件内容需要存储到指定的内容数据结构当中。
 * 2.查找要求有独立线程来执行，直接消费读取线程池产生的内存数据结构。
 * 3.文件读取和排序要求并发作业，文件读取只要产生了数据，就可以把数据交给排序线程进行消费，计算最小值。
 * 代码结构要求
 * 1.重上面的要求语意里面抽象出合适的设计模式。
 * 2.需要考虑多线程的并发控制，同步机制。
 * 3.代码实现只能用JDK1.6或者1.8自带的工具类
 */
public abstract class DoWorkTemplate {

    ExecutorService threadPool = Executors.newFixedThreadPool(10);

    LinkedBlockingQueue<MFile> queue = new LinkedBlockingQueue<MFile>();

    ConcurrentHashMap<Integer,MFile> concurrentHashMap = new ConcurrentHashMap<>();

    CountDownLatch countDownLatch;

    protected void doWork(){
        long startTime = System.currentTimeMillis();
        //1.寻找文件 getFilePath(),getFileSuffix()是两个钩子方法，可以通过不同的文件路径和后缀来获得文件
        List<File> fileList = getFiles(new ArrayList<File>(),getFilePath(),getFileSuffix());
        countDownLatch = new CountDownLatch(fileList.size() + 1);

        long getFilesTime = System.currentTimeMillis() - startTime;
        System.out.println("获得文件的毫秒时间 : "+getFilesTime + "ms");

        //2.多线程读文件放入同步队列中
        for (File file : fileList) {
            threadPool.execute(new ReadFileThread(this,file));
        }
        long gereadTime = System.currentTimeMillis() - startTime;
        System.out.println("并发读文件的毫秒时间 : "+gereadTime + "ms");
        //3.排序
        sortFile();

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadPool.shutdown();

        long sortTime = System.currentTimeMillis() - startTime;
        System.out.println("并发添加元素："+sortTime +"ms");

        //4.输出787
        TreeMap<Integer,MFile> treeMap = new TreeMap<>();
        treeMap.putAll(concurrentHashMap);
        for (MFile file : treeMap.values()) {
            System.out.println(file.toString());
        }

        long lastTime = System.currentTimeMillis() - startTime;
        System.out.println("--------------------------------------the work end" +lastTime);

    }

    private void sortFile() {
        MFile file = null;
        while(true){
           if(queue.isEmpty() && countDownLatch.getCount() <= 1) {
               countDownLatch.countDown();
               break;
           }
            try {
                file = queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

           threadPool.execute(new SortFileThread(file, this));
        }

    }

    protected abstract File getFilePath();

    protected abstract String getFileSuffix();

    public List<File> getFiles(List<File> fileList,File file, String suffix){
        for (File f1 : file.listFiles()) {
            if(f1.isDirectory()){
                getFiles(fileList,f1,suffix);
            }else{
                if(f1.getName().endsWith(suffix)){
                    fileList.add(f1);
                }
            }
        }
        return fileList;
    }
}
